#include "tfrmcalibunit.h"
#include "ui_tfrmcalibunit.h"
#include <QMessageBox>

TFrmCalibUnit::TFrmCalibUnit(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TFrmCalibUnit)
{
    ui->setupUi(this);
    ui->progressBar->setValue(0);
    ui->btnStop->setVisible(false);
    ui->leDestVal->setRange(0,65535);
    ui->leMeasVal->setReadOnly(true);
    ui->leMeasVal->setPlaceholderText("未刷新");
    ui->leMeasVal->setVisible(true);

    //信号槽_校准开始/停止按钮点击
    connect(ui->btnStart,&QPushButton::clicked,this,&TFrmCalibUnit::slotBtnStartClicked);
    connect(ui->btnStop,&QPushButton::clicked,this,&TFrmCalibUnit::slotBtnStopClicked);
    //信号槽_结构体数据更新
    connect(TLR::get(),&TLR::sigStructDataUpdate_Calib,this,&TFrmCalibUnit::slotStructDataUpdate);
    //信号槽_定时读取定时器
    m_tmRd = new QTimer(this);
    connect(m_tmRd,&QTimer::timeout,this,&TFrmCalibUnit::slotRd);
    //信号槽_校准开始结束
    connect(TLR::get(),&TLR::sigCalibStarted,this,&TFrmCalibUnit::slotCalibStarted);
    connect(TLR::get(),&TLR::sigCalibStoped,this,&TFrmCalibUnit::slotCalibStoped);
}

TFrmCalibUnit::~TFrmCalibUnit()
{
    delete ui;
}

/**
 * @brief 重置
 * @param calib
 */
void TFrmCalibUnit::reset(const TLRCalib &calib)
{
    m_calib = calib;
    ui->progressBar->setRange(0,m_calib.CalibCnt);
    ui->groupBox->setTitle(calib.Name);
    ui->leDestVal->setValue(m_calib.DestVal);
}

/**
 * @brief 设置ID
 * @param id
 */
void TFrmCalibUnit::setID(int id)
{
    m_id = id;
}

/**
 * @brief 比例校准
 */
void TFrmCalibUnit::calib_ratio()
{
    //-1- 计算平均值
    s64 ave_val = 0;
    s64 sum_val = 0;
    for(int i=0;i<m_meas_samples.size();i++) {
        sum_val += m_meas_samples.at(i);
    }
    ave_val = sum_val * 1.0 / m_meas_samples.size();
    if(ave_val <= 0) {
        ui->progressBar->setValue(0);
        ui->btnStart->setVisible(true);
        ui->btnStop->setVisible(false);
        emit TLR::get()->sigCalibStoped();
        QMessageBox::warning(this,"警告","测量值全0，无法校准");
        return;
    }
    //-2- 计算新校准值并且写入校准值区域
    s64 newCalibVal = m_originCalibVal * 1.0 * m_destVal / ave_val;
    emit TLR::get()->sigCalibWrPara(m_calib.calib.sta,m_calib.calib.len,m_calib.calib.type,newCalibVal);
    ui->btnStart->setVisible(true);
    ui->btnStop->setVisible(false);
    emit TLR::get()->sigCalibStoped();
    QMessageBox::information(this,"提示","校准未完成");
}

/**
 * @brief 偏移校准
 */
void TFrmCalibUnit::calib_offset()
{
    //-1- 计算平均值
    s64 ave_val = 0;
    s64 sum_val = 0;
    for(int i=0;i<m_meas_samples.size();i++) {
        sum_val += m_meas_samples.at(i);
    }
    ave_val = sum_val * 1.0 / m_meas_samples.size();
    //-2- 平均值写入校准值区域
    emit TLR::get()->sigCalibWrPara(m_calib.calib.sta,m_calib.calib.len,m_calib.calib.type,ave_val);
    //-3- 将目标值写入校准值扩展区域
    if(m_calib.calibExt.isValid()) {
        emit TLR::get()->sigCalibWrPara(m_calib.calibExt.sta,m_calib.calibExt.len,m_calib.calibExt.type,m_destVal);
    }
    ui->btnStart->setVisible(true);
    ui->btnStop->setVisible(false);
    emit TLR::get()->sigCalibStoped();
    QMessageBox::information(this,"提示","校准完成");
}

/**
 * @brief 7022E校准
 */
void TFrmCalibUnit::calib_7022()
{
    //-1- 计算平均值
    s64 ave_val = 0;
    s64 sum_val = 0;
    for(int i=0;i<m_meas_samples.size();i++) {
        sum_val += m_meas_samples.at(i);
    }
    ave_val = sum_val * 1.0 / m_meas_samples.size();
    if(ave_val <= 0) {
        ui->progressBar->setValue(0);
        ui->btnStart->setVisible(true);
        ui->btnStop->setVisible(false);
        emit TLR::get()->sigCalibStoped();
        QMessageBox::warning(this,"警告","测量值全0，无法校准");
        return;
    }
    //-2- 计算新校准值并且写入校准值区域
    double k = m_destVal * 1.0 / ave_val;
    s32 calib_val_tmp = (m_originCalibVal << 8) + 0x7fffffff;
    calib_val_tmp *= k;
    calib_val_tmp -= 0x7fffffff;
    calib_val_tmp >>= 8;
    u16 new_calib_val_h = (calib_val_tmp >> 16) & 0xff;
    u16 new_calib_val_l = calib_val_tmp & 0xffff;
    s32 new_valib_val = new_calib_val_h << 16 | new_calib_val_l;
    emit TLR::get()->sigCalibWrPara(m_calib.calib.sta,m_calib.calib.len,m_calib.calib.type,new_valib_val);
    ui->btnStart->setVisible(true);
    ui->btnStop->setVisible(false);
    emit TLR::get()->sigCalibStoped();
    QMessageBox::information(this,"提示","校准完成");
}

/**
 * @brief 校准按钮点击
 */
void TFrmCalibUnit::slotBtnStartClicked()
{
    if(m_calib.CalibCnt <= 0) {
        QMessageBox::warning(this,"警告","配置的采样次数小于等于0，无法校准");
        return;
    }
    if((m_calib.type < 0) || (m_calib.type > 2)) {
        QMessageBox::warning(this,"警告","校准类型错误，无法校准");
        return;
    }
    if(!m_calib.meas.isValid() || !m_calib.calib.isValid()) {
        QMessageBox::warning(this,"警告","测量或校准未正确配置，无法校准");
        return;
    }
    m_destVal = ui->leDestVal->value();
    if(m_destVal < 0) {
        QMessageBox::warning(this,"警告","请输入正确的目标值");
        return;
    }
    m_calibValInit = false;
    m_meas_samples.clear();
    ui->progressBar->setValue(0);
    m_tmRd->start(100);
    ui->btnStart->setVisible(false);
    ui->btnStop->setVisible(true);
    emit TLR::get()->sigCalibStarted(m_id);
}

/**
 * @brief 校准停止点击
 */
void TFrmCalibUnit::slotBtnStopClicked()
{
    m_tmRd->stop();
    ui->btnStart->setVisible(true);
    ui->btnStop->setVisible(false);
    emit TLR::get()->sigCalibStoped();
}

/**
 * @brief 结构体数据更新
 * @param sta 起始地址
 * @param struct_sta 结构体起始地址
 * @param len 长度
 * @param 原始数据
 */
void TFrmCalibUnit::slotStructDataUpdate(int sta,int struct_sta,int len,const QByteArray &data)
{
    if(ui->btnStart->isVisible()) {
        return;
    }
    if((sta == m_calib.meas.sta) && (len == m_calib.meas.len)) {
        s64 meas_val = 0x00;
        if(m_calib.meas.type == "u16") {
            meas_val = *(u16*)(data.data() + (sta - struct_sta));
        }
        else if(m_calib.meas.type == "s16") {
            meas_val = *(s16*)(data.data() + (sta - struct_sta));
        }
        else if(m_calib.meas.type == "u32") {
            meas_val = *(u32*)(data.data() + (sta - struct_sta));
        }
        else if(m_calib.meas.type == "s32") {
            meas_val = *(s32*)(data.data() + (sta - struct_sta));
        }
        m_meas_samples.append(meas_val);
        ui->progressBar->setValue(m_meas_samples.size());
        if(m_meas_samples.size() >= m_calib.CalibCnt) {
            m_tmRd->stop();
            if(m_calib.type == calibRatio) {
                calib_ratio();
            }
            else if(m_calib.type == calibOffset) {
                calib_offset();
            }
            else if(m_calib.type == calib7022) {
                calib_7022();
            }
        }
    }
    else if((sta == m_calib.calib.sta) && (len == m_calib.calib.len)) {
        if(m_calib.calib.type == "u16") {
            m_originCalibVal = *(u16*)(data.data() + (sta - struct_sta));
        }
        else if(m_calib.calib.type == "s16") {
            m_originCalibVal = *(s16*)(data.data() + (sta - struct_sta));
        }
        else if(m_calib.calib.type == "u32") {
            m_originCalibVal = *(u32*)(data.data() + (sta - struct_sta));
        }
        else if(m_calib.calib.type == "s32") {
            m_originCalibVal = *(s32*)(data.data() + (sta - struct_sta));
        }
        m_calibValInit = true;
    }
}

/**
 * @brief 定时读取
 */
void TFrmCalibUnit::slotRd()
{
    if(!m_calibValInit) {
        emit TLR::get()->sigCalibRdPara(m_calib.calib.sta,m_calib.calib.len);
    }
    else {
        emit TLR::get()->sigCalibRdPara(m_calib.meas.sta,m_calib.meas.len);
    }
}

/**
 * @brief 校准开始
 * @param id
 */
void TFrmCalibUnit::slotCalibStarted(int id)
{
    ui->groupBox->setEnabled(id == m_id);
}

/**
 * @brief 校准结束
 * @param id
 */
void TFrmCalibUnit::slotCalibStoped()
{
    ui->groupBox->setEnabled(true);
}
